//
//  BRRequestManager.m
//  BrezzeSaaS
//
//  Created by IOS on 2021/9/1.
//  Copyright © 2021 Brezze GWG. All rights reserved.
//

#import "BRRequestManager.h"
#import <SystemConfiguration/SystemConfiguration.h>

/*
 * 创建静态的实例变量
 */
static BRRequestManager *manager = nil;

static NSURLSession *session = nil;

static NSString *_currentRequestURL = nil;  // 当前请求的URL，用于判断是否需要显示错误提示

@implementation BRRequestManager


#pragma mark - 单例初始化
+ (instancetype)shared {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[BRRequestManager alloc]init];
        
        // 创建NSURLSession配置
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        config.timeoutIntervalForRequest = 30.0;
        config.timeoutIntervalForResource = 30.0;
        config.HTTPShouldSetCookies = YES;
        config.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
        
        // 创建NSURLSession
        session = [NSURLSession sessionWithConfiguration:config];
    });
    return manager;
}

/**
 网络请求初始化
 @param params 请求入参
 */
- (void)requestWithHttpType:(REQUEST_TYPE)type url:(NSString *)url params:(nullable NSDictionary *)params succeed:(SucceedBlock)succeed failed:(Failed)failed {
    /*
     * 网络请求数据初始化
     * 判断Token、UID是否存在，并且赋值给请求头
     */
    
    /*
     * 判断请求方式
     */
    if (type == POST || type == PATCH || type == PUT) {
        
        [self dataTaskWithRequest:url params:params succeed:succeed failed:failed byMethod:type];
    }
    
}

- (void)br_config {
    // 这个方法现在主要用于配置，实际配置在创建请求时进行
    // 保持方法存在以兼容现有代码
}

- (NSMutableURLRequest *)br_configRequest:(NSString *)tempUrl parmas:(nullable NSDictionary *)params byMethod:(REQUEST_TYPE)type {
    NSString *typeStr = [self getRequestTypeStr:type];
    
    NSURL *url = [NSURL URLWithString:tempUrl];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:typeStr];
    
    // 设置通用请求头
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    
    // 语言
    NSString *headerLanguage = [BRTools br_requstLanguage];
    [request setValue:headerLanguage forHTTPHeaderField:@"brezze-language"];
    // 时区
    [request setValue:[MINUtils getCusZoneString] forHTTPHeaderField:@"zone"];
    // 手机型号
    [request setValue:[MINUtils getIphoneType] forHTTPHeaderField:@"phoneModel"];
    // 版本号
    [request setValue:@"1" forHTTPHeaderField:@"apptype"];
    [request setValue:[MINUtils getBundleNum] forHTTPHeaderField:@"appversion"];
    // uid
    [request setValue:[BRTools getDeviceUUIDStr] forHTTPHeaderField:@"deviceMac"];
    
    // 添加请求头
    if (USERManager.token.length != 0 && USERManager.isLogin) {
        [request setValue:USERManager.token forHTTPHeaderField:@"token"];
    } else {
        [request setValue:@"" forHTTPHeaderField:@"token"];
    }
    
    if (USERManager.isLogin == YES) {
        if (USERManager.loginTenantId.length != 0) {
            [request setValue:USERManager.loginTenantId forHTTPHeaderField:@"platform-id"];
            NSLog(@"\nUSERManager loginTenantId = %@",USERManager.loginTenantId);
        } else {
            [request setValue:USERManager.tenantModel.platformId forHTTPHeaderField:@"platform-id"];
        }
    }
    
    // 设置请求体
    NSData *body = nil;
    if (params != nil) {
        body = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil];
        [request setHTTPBody:body];
        [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)body.length] forHTTPHeaderField:@"Content-Length"];
    }
    
    // 添加 Cookie 到请求头（如果有的话）
    NSArray<NSHTTPCookie *> *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url];
    if (cookies.count > 0) {
        NSDictionary *cookieHeaders = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
        [cookieHeaders enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
            [request setValue:value forHTTPHeaderField:key];
        }];
    }
    
    NSLog(@"token = %@ \nplatformId = %@ \nloginTenantId = %@",USERManager.token,USERManager.tenantModel.platformId,USERManager.loginTenantId);
    
    return request;
}

- (NSString *)getRequestTypeStr:(REQUEST_TYPE)type {
    
    if (type == POST) {
        return @"POST";
    }else if (type == GET) {
        return @"GET";
    }else if (type == DELETE) {
        return @"DELETE";
    }else if (type == PUT) {
        return @"PUT";
    }
    
    return @"PATCH";
}

#pragma mark - POST请求
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSString *)url params:(nullable NSDictionary *)params succeed:(SucceedBlock)succeed failed:(Failed)failed byMethod:(REQUEST_TYPE)type {
    
    [self br_config];
    
    /*
     * 开始请求
     */
    NSString *tempUrl = url;
    
    NSMutableURLRequest *request = [self br_configRequest:tempUrl parmas:params byMethod:type];
    
    NSLog(@"\n ******%@请求头:****** \n %@",request.HTTPMethod,request.allHTTPHeaderFields);
    NSLog(@"\n ******%@接口请求****** \n💻请求路径: %@ \n💻请求参数: %@ \n******请求END******\n", request.HTTPMethod, url, params);
    
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // 保存 Cookie（从响应头中提取）
        if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSArray<NSHTTPCookie *> *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:httpResponse.allHeaderFields forURL:httpResponse.URL];
            if (cookies.count > 0) {
                [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:httpResponse.URL mainDocumentURL:nil];
            }
        }
        
        if (error) {
            NSLog(@"请求失败 err = %@ \n url = %@\n 参数= %@",error,tempUrl,params);
            
            // 尝试从错误响应中提取错误信息
            NSString *errorMessage = error.localizedDescription;
            NSInteger businessCode = error.code;
            
            // 尝试从响应数据中获取错误信息
            if (data && data.length > 0) {
                NSError *jsonError = nil;
                id errorObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                if (!jsonError && [errorObject isKindOfClass:[NSDictionary class]]) {
                    NSDictionary *errorDict = (NSDictionary *)errorObject;
                    
                    // 优先从 data 字段中提取错误信息（data 可能是字符串格式的 JSON）
                    id dataObj = errorDict[@"data"];
                    if (dataObj) {
                        NSDictionary *dataDict = nil;
                        
                        // 如果 data 是字符串，尝试解析为 JSON
                        if ([dataObj isKindOfClass:[NSString class]]) {
                            NSString *dataString = (NSString *)dataObj;
                            if (dataString.length > 0) {
                                NSData *dataJsonData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
                                if (dataJsonData) {
                                    NSError *dataJsonError = nil;
                                    id parsedDataObj = [NSJSONSerialization JSONObjectWithData:dataJsonData options:0 error:&dataJsonError];
                                    if (!dataJsonError && [parsedDataObj isKindOfClass:[NSDictionary class]]) {
                                        dataDict = (NSDictionary *)parsedDataObj;
                                    }
                                }
                            }
                        }
                        // 如果 data 已经是字典
                        else if ([dataObj isKindOfClass:[NSDictionary class]]) {
                            dataDict = (NSDictionary *)dataObj;
                        }
                        
                        // 从 data 字典中提取错误消息（优先级：data.msg > data.message）
                        if (dataDict) {
                            NSString *dataMsg = dataDict[@"msg"];
                            if (dataMsg && [dataMsg isKindOfClass:[NSString class]] && dataMsg.length > 0) {
                                errorMessage = dataMsg;
                            } else {
                                NSString *dataMessage = dataDict[@"message"];
                                if (dataMessage && [dataMessage isKindOfClass:[NSString class]] && dataMessage.length > 0) {
                                    errorMessage = dataMessage;
                                }
                            }
                        }
                    }
                    
                    // 如果从 data 中没有提取到，从顶层提取（优先级：msg > message）
                    if ([errorMessage isEqualToString:error.localizedDescription]) {
                        NSString *msg = errorDict[@"msg"];
                        if (msg && [msg isKindOfClass:[NSString class]] && msg.length > 0) {
                            errorMessage = msg;
                        } else {
                            NSString *message = errorDict[@"message"];
                            if (message && [message isKindOfClass:[NSString class]] && message.length > 0) {
                                errorMessage = message;
                            }
                        }
                    }
                    
                    // 提取业务错误码（如果存在）
                    if (errorDict[@"code"]) {
                        businessCode = [errorDict[@"code"] integerValue];
                    }
                }
            }
            
            // 确保回调在主线程执行
            dispatch_async(dispatch_get_main_queue(), ^{
                failed(businessCode, errorMessage);
                [self handleCode:errorMessage code:businessCode];
            });
        } else {
            // 解析响应数据
            NSDictionary *dic = nil;
            if (data && data.length > 0) {
                NSError *jsonError = nil;
                id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                if (!jsonError && [responseObject isKindOfClass:[NSDictionary class]]) {
                    dic = (NSDictionary *)responseObject;
                }
            }
            
            if (!dic) {
                dic = @{};
            }
            
            NSInteger status = [dic[@"code"] integerValue];
            
            // 获取错误消息（优先使用msg，如果没有则使用message）
            NSString *errorMsg = dic[@"msg"] ?: dic[@"message"] ?: @"";
            
            // 判断是否成功：code为0或200表示成功，或者msg为OK/success也表示成功
            BOOL isSuccess = (status == 0 || status == 200);
            if (isSuccess) {
                // 如果code是0或200，但msg包含错误信息，需要进一步判断
                NSString *lowerMsg = errorMsg.lowercaseString;
                if (errorMsg.length > 0 && 
                    ![lowerMsg containsString:@"ok"] && 
                    ![lowerMsg containsString:@"success"] &&
                    ![lowerMsg isEqualToString:@""]) {
                    // msg不为空且不是OK/success，认为是错误信息
                    isSuccess = NO;
                }
            }
            
            // 确保回调在主线程执行
            dispatch_async(dispatch_get_main_queue(), ^{
                if (isSuccess) {
                    NSLog(@"请求 成功 - code:%ld msg:%@", (long)status, errorMsg ?: @"无");
                    succeed(dic, status);
                } else {
                    // status != 0 且 != 200，或者有错误信息，走失败逻辑
                    NSLog(@"失败 URL = %@ params = %@\n",tempUrl,params);
                    NSLog(@"失败信息 - code:%ld msg:%@ message:%@", (long)status, dic[@"msg"] ?: @"无", dic[@"message"] ?: @"无");
                    // 使用msg字段，如果没有则使用message字段
                    NSString *finalErrorMsg = errorMsg.length > 0 ? errorMsg : @"请求失败";
                    failed(status, finalErrorMsg);
                    if (status == 21012) {
                        return;
                    }
                    
                    [self handleCode:finalErrorMsg code:status];
                }
            });
        }
    }];
    [task resume];
    return task;
}


- (NSURLSessionDataTask *)POST:(NSString *)url params:(nullable NSDictionary *)params succeed:(SucceedBlock)succeed failed:(Failed)failed  {
    

    NSString *tempUrl = [BASE_URL stringByAppendingString:url];
    
    return [self dataTaskWithRequest:tempUrl params:params succeed:succeed failed:failed byMethod:POST];
}

/// POST请求（表单格式，application/x-www-form-urlencoded）
- (NSURLSessionDataTask *)POSTWithFormData:(NSString *)url params:(nullable NSDictionary *)params succeed:(SucceedBlock)succeed failed:(Failed)failed {
    [self br_config];
    
    NSString *tempUrl = url;
    if (![url containsString:@"https://"]) {
        tempUrl = [BASE_URL stringByAppendingString:url];
    }
    
    // 保存当前请求URL，用于错误处理时判断
    _currentRequestURL = tempUrl;
    
    // 创建表单格式的请求体
    NSMutableString *bodyString = [NSMutableString string];
    if (params != nil && params.count > 0) {
        NSArray *keys = params.allKeys;
        for (NSInteger i = 0; i < keys.count; i++) {
            NSString *key = keys[i];
            NSString *value = [NSString stringWithFormat:@"%@", params[key]];
            
            // URL编码：使用标准的 URLQueryAllowedCharacterSet，但排除 & 和 = 字符
            NSMutableCharacterSet *allowedCharacters = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
            [allowedCharacters removeCharactersInString:@"&="];
            NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
            NSString *encodedValue = [value stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
            
            if (i > 0) {
                [bodyString appendString:@"&"];
            }
            [bodyString appendFormat:@"%@=%@", encodedKey, encodedValue];
        }
    }
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:tempUrl]];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    
    // 设置请求头
    if (USERManager.token.length != 0 && USERManager.isLogin) {
        [request setValue:USERManager.token forHTTPHeaderField:@"token"];
    } else {
        [request setValue:@"" forHTTPHeaderField:@"token"];
    }
    
    if (USERManager.isLogin) {
        if (USERManager.loginTenantId.length != 0) {
            [request setValue:USERManager.loginTenantId forHTTPHeaderField:@"platform-id"];
        } else if (USERManager.tenantModel.platformId.length != 0) {
            [request setValue:USERManager.tenantModel.platformId forHTTPHeaderField:@"platform-id"];
        }
    }
    
    // 语言
    NSString *headerLanguage = [BRTools br_requstLanguage];
    [request setValue:headerLanguage forHTTPHeaderField:@"brezze-language"];
    // 时区
    [request setValue:[MINUtils getCusZoneString] forHTTPHeaderField:@"zone"];
    // 手机型号
    [request setValue:[MINUtils getIphoneType] forHTTPHeaderField:@"phoneModel"];
    // 版本号
    [request setValue:@"1" forHTTPHeaderField:@"apptype"];
    [request setValue:[MINUtils getBundleNum] forHTTPHeaderField:@"appversion"];
    // deviceMac
    [request setValue:[BRTools getDeviceUUIDStr] forHTTPHeaderField:@"deviceMac"];
    
    // 添加 Cookie 到请求头（如果有的话）
    NSURL *urlObj = [NSURL URLWithString:tempUrl];
    NSArray<NSHTTPCookie *> *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:urlObj];
    if (cookies.count > 0) {
        NSDictionary *cookieHeaders = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
        [cookieHeaders enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
            [request setValue:value forHTTPHeaderField:key];
        }];
    }
    
    NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
    [request setHTTPBody:bodyData];
    [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)bodyData.length] forHTTPHeaderField:@"Content-Length"];
    
    NSLog(@"\n ******POST表单格式请求头:****** \n %@", request.allHTTPHeaderFields);
    NSLog(@"\n ******POST表单格式接口请求****** \n💻请求路径: %@ \n💻请求参数: %@ \n请求体: %@ \n******请求END******\n", request.HTTPMethod, tempUrl, params, bodyString);
    
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        // 保存 Cookie（从响应头中提取）
        if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSArray<NSHTTPCookie *> *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:httpResponse.allHeaderFields forURL:httpResponse.URL];
            if (cookies.count > 0) {
                [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:httpResponse.URL mainDocumentURL:nil];
                NSLog(@"🍪 保存了 %lu 个 Cookie", (unsigned long)cookies.count);
                for (NSHTTPCookie *cookie in cookies) {
                    NSLog(@"  - %@ = %@", cookie.name, cookie.value.length > 50 ? [cookie.value substringToIndex:50] : cookie.value);
                }
            }
        }
        
        if (error) {
            NSLog(@"请求失败 err = %@ \n url = %@\n 参数= %@", error, tempUrl, params);
            
            // 尝试从错误响应中提取错误信息
            NSString *errorMessage = error.localizedDescription;
            NSInteger businessCode = error.code;
            
            // 尝试从响应数据中获取错误信息
            NSData *errorData = data;
            if (errorData && errorData.length > 0) {
                NSError *jsonError = nil;
                id errorObject = [NSJSONSerialization JSONObjectWithData:errorData options:0 error:&jsonError];
                if (!jsonError && [errorObject isKindOfClass:[NSDictionary class]]) {
                    NSDictionary *errorDict = (NSDictionary *)errorObject;
                    
                    // 优先从 data 字段中提取错误信息（data 可能是字符串格式的 JSON）
                    id dataObj = errorDict[@"data"];
                    if (dataObj) {
                        NSDictionary *dataDict = nil;
                        
                        // 如果 data 是字符串，尝试解析为 JSON
                        if ([dataObj isKindOfClass:[NSString class]]) {
                            NSString *dataString = (NSString *)dataObj;
                            if (dataString.length > 0) {
                                NSData *dataJsonData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
                                if (dataJsonData) {
                                    NSError *dataJsonError = nil;
                                    id parsedDataObj = [NSJSONSerialization JSONObjectWithData:dataJsonData options:0 error:&dataJsonError];
                                    if (!dataJsonError && [parsedDataObj isKindOfClass:[NSDictionary class]]) {
                                        dataDict = (NSDictionary *)parsedDataObj;
                                    }
                                }
                            }
                        }
                        // 如果 data 已经是字典
                        else if ([dataObj isKindOfClass:[NSDictionary class]]) {
                            dataDict = (NSDictionary *)dataObj;
                        }
                        
                        // 从 data 字典中提取错误消息（优先级：data.msg > data.message）
                        if (dataDict) {
                            NSString *dataMsg = dataDict[@"msg"];
                            if (dataMsg && [dataMsg isKindOfClass:[NSString class]] && dataMsg.length > 0) {
                                errorMessage = dataMsg;
                            } else {
                                NSString *dataMessage = dataDict[@"message"];
                                if (dataMessage && [dataMessage isKindOfClass:[NSString class]] && dataMessage.length > 0) {
                                    errorMessage = dataMessage;
                                }
                            }
                        }
                    }
                    
                    // 如果从 data 中没有提取到，从顶层提取（优先级：msg > message）
                    if ([errorMessage isEqualToString:error.localizedDescription]) {
                        NSString *msg = errorDict[@"msg"];
                        if (msg && [msg isKindOfClass:[NSString class]] && msg.length > 0) {
                            errorMessage = msg;
                        } else {
                            NSString *message = errorDict[@"message"];
                            if (message && [message isKindOfClass:[NSString class]] && message.length > 0) {
                                errorMessage = message;
                            }
                        }
                    }
                    
                    // 提取业务错误码（如果存在）
                    if (errorDict[@"code"]) {
                        businessCode = [errorDict[@"code"] integerValue];
                    }
                }
            }
            
            // 确保回调在主线程执行
            dispatch_async(dispatch_get_main_queue(), ^{
                failed(businessCode, errorMessage);
                [self handleCode:errorMessage code:businessCode];
            });
        } else {
            // 检查 HTTP 状态码
            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
            NSInteger httpStatusCode = httpResponse ? httpResponse.statusCode : 0;
            
            // 解析响应数据
            NSDictionary *dic = nil;
            if (data && data.length > 0) {
                NSError *jsonError = nil;
                id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                if (!jsonError && [responseObject isKindOfClass:[NSDictionary class]]) {
                    dic = (NSDictionary *)responseObject;
                }
            }
            if (!dic) {
                dic = @{};
            }
            
            if (![dic isKindOfClass:[NSDictionary class]]) {
                // 如果响应不是字典，检查 HTTP 状态码
                // 确保回调在主线程执行
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (httpStatusCode >= 200 && httpStatusCode < 300) {
                        NSLog(@"请求成功 (HTTP %ld)", httpStatusCode);
                        succeed(@{}, httpStatusCode);
                    } else {
                        NSLog(@"失败 URL = %@ HTTP状态码 = %ld", tempUrl, httpStatusCode);
                        failed(httpStatusCode, @"请求失败");
                    }
                });
                return;
            }
            
            // 检查 code 字段是否存在
            BOOL hasCodeField = [dic objectForKey:@"code"] != nil;
            NSInteger status = hasCodeField ? [dic[@"code"] integerValue] : NSIntegerMin;
            
            // 获取错误消息（新接口用 msg，旧接口用 message）
            NSString *msg = dic[@"msg"] ?: dic[@"message"] ?: @"";
            
            // 判断是否成功的逻辑（更灵活）
            BOOL isSuccess = NO;
            
            // 1. 优先检查 HTTP 状态码（2xx 表示成功）
            if (httpStatusCode >= 200 && httpStatusCode < 300) {
                // 2. 检查 msg 是否为成功标志（OK、空字符串等）
                if ([msg isEqualToString:@"OK"] || [msg isEqualToString:@"ok"] || msg.length == 0) {
                    isSuccess = YES;
                }
                // 3. 如果 code 字段存在，检查 code 值
                else if (hasCodeField) {
                    // code 可能是 0, 200, -1 等都表示成功
                    if (status == 0 || status == 200 || status == -1) {
                        // 如果 code 是这些值，且 msg 不是明显的错误消息，认为是成功
                        NSString *lowerMsg = [msg lowercaseString];
                        if (![lowerMsg containsString:@"error"] && 
                            ![lowerMsg containsString:@"fail"] && 
                            ![lowerMsg containsString:@"失败"] &&
                            ![lowerMsg containsString:@"错误"]) {
                            isSuccess = YES;
                        }
                    }
                }
                // 4. 如果没有 code 字段，且 HTTP 状态码是成功的，且 msg 不是错误，认为是成功
                else {
                    // 没有 code 字段时，只要 HTTP 状态码成功且 msg 不是错误消息，就认为成功
                    NSString *lowerMsg = [msg lowercaseString];
                    if (![lowerMsg containsString:@"error"] && 
                        ![lowerMsg containsString:@"fail"] && 
                        ![lowerMsg containsString:@"失败"] &&
                        ![lowerMsg containsString:@"错误"]) {
                        isSuccess = YES;
                    }
                }
            }
            
            // 确保回调在主线程执行
            dispatch_async(dispatch_get_main_queue(), ^{
                if (isSuccess) {
                    NSInteger respCode = hasCodeField ? status : httpStatusCode;
                    NSLog(@"请求成功 - HTTP:%ld code:%@ msg:%@", httpStatusCode, hasCodeField ? @(status).stringValue : @"无", msg);
                    _currentRequestURL = nil;  // 请求成功，清除URL
                    succeed(dic, respCode);
                } else {
                    NSInteger errorCode = hasCodeField ? status : httpStatusCode;
                    NSLog(@"失败 URL = %@ HTTP:%ld code:%@ msg:%@", tempUrl, httpStatusCode, hasCodeField ? @(status).stringValue : @"无", msg);
                    NSString *errorMsg = msg.length > 0 ? msg : @"请求失败";
                    failed(errorCode, errorMsg);
                    if (status == 21012) {
                        _currentRequestURL = nil;  // 清除URL
                        return;
                    }
                    
                    [self handleCode:errorMsg code:errorCode];
                }
            });
        }
    }];
    
    [task resume];
    return task;
}

- (NSURLSessionDataTask *)PUT:(NSString *)url params:(nullable NSDictionary *)params succeed:(SucceedBlock)succeed failed:(Failed)failed {

    NSString *tempUrl = [BASE_URL stringByAppendingString:url];
    
    return [self dataTaskWithRequest:tempUrl params:params succeed:succeed failed:failed byMethod:PUT];
}

- (NSURLSessionDataTask *)GET:(NSString *)url params:(nullable NSDictionary *)params succeed:(SucceedBlock)succeed failed:(Failed)failed  {
    
    [self br_config];
    NSString *tempUrl = url;
    if (![url containsString:@"https://"]) {
        tempUrl = [BASE_URL stringByAppendingString:url];
    }
//    NSString *tempUrl = [BASE_URL stringByAppendingString:url];
    
    // 保存当前请求URL，用于错误处理时判断
    _currentRequestURL = tempUrl;
    
    // 打印完整的请求信息
    NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    NSLog(@"📤 GET 请求");
    NSLog(@"URL: %@", tempUrl);
    NSLog(@"入参: %@", params ?: @"无参数");
    NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
    
    // 构建GET请求URL（如果有参数，添加到URL中）
    NSMutableString *fullUrl = [NSMutableString stringWithString:tempUrl];
    if (params && params.count > 0) {
        NSMutableArray *queryItems = [NSMutableArray array];
        for (NSString *key in params.allKeys) {
            NSString *value = [NSString stringWithFormat:@"%@", params[key]];
            NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
            NSString *encodedValue = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
            [queryItems addObject:[NSString stringWithFormat:@"%@=%@", encodedKey, encodedValue]];
        }
        if (queryItems.count > 0) {
            NSString *queryString = [queryItems componentsJoinedByString:@"&"];
            [fullUrl appendFormat:@"?%@", queryString];
        }
    }
    
    NSMutableURLRequest *request = [self br_configRequest:fullUrl parmas:nil byMethod:GET];
    [request setHTTPMethod:@"GET"];
    
    NSURLSessionDataTask *requestTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 保存 Cookie（从响应中提取）
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        if (httpResponse) {
            NSArray<NSHTTPCookie *> *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:httpResponse.allHeaderFields forURL:httpResponse.URL];
            if (cookies.count > 0) {
                [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:httpResponse.URL mainDocumentURL:nil];
                NSLog(@"🍪 GET请求保存了 %lu 个 Cookie", (unsigned long)cookies.count);
            }
        }
        
        // 获取HTTP状态码
        NSInteger httpStatusCode = httpResponse ? httpResponse.statusCode : 0;
        
        if (error) {
            // 确保URL已保存（可能在并发请求时被覆盖，所以重新设置）
            _currentRequestURL = tempUrl;
            
            // 打印完整的错误信息
            NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            NSLog(@"❌ 请求失败");
            NSLog(@"URL: %@", tempUrl);
            NSLog(@"参数: %@", params);
            NSLog(@"错误码: %ld", (long)error.code);
            NSLog(@"错误描述: %@", error.localizedDescription);
            NSLog(@"错误域: %@", error.domain);
            
            // 尝试解析服务器返回的错误数据
            if (data && data.length > 0) {
                NSError *jsonError = nil;
                id errorObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
                if (!jsonError && errorObject) {
                    NSLog(@"服务器返回的错误数据:");
                    if ([errorObject isKindOfClass:[NSDictionary class]]) {
                        NSDictionary *errorDict = (NSDictionary *)errorObject;
                        NSLog(@"错误JSON: %@", errorDict);
                    } else {
                        NSLog(@"错误数据: %@", errorObject);
                    }
                }
            }
            
            NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
            
            // 添加容错处理
            NSString *errorMessage = error.localizedDescription;
            NSInteger businessCode = 0; // 业务错误码
            
            // 特殊处理：rentbox/show.html/V2 接口的 3840 错误（表示有正在进行中的订单或未支付的订单）
            if (error.code == 3840 && [tempUrl containsString:@"/sw/app/rentbox/show.html/V2"]) {
                errorMessage = @"当前有正在进行中的订单或未支付的订单";
                businessCode = 3840;
                NSLog(@"📍 [rentbox/show.html/V2] 检测到3840错误，表示有进行中的订单或未支付订单");
            } else if (error.code == NSURLErrorTimedOut) {
                errorMessage = @"请求超时，请检查网络连接";
            } else if (error.code == NSURLErrorCannotConnectToHost) {
                errorMessage = @"无法连接到服务器，请检查网络";
            } else if (error.code == NSURLErrorNotConnectedToInternet) {
                errorMessage = @"网络连接失败，请检查网络设置";
            } else if (data && data.length > 0) {
                // 尝试从响应数据中提取错误消息和业务错误码
                NSError *jsonError = nil;
                id errorObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                if (!jsonError && [errorObject isKindOfClass:[NSDictionary class]]) {
                    NSDictionary *errorDict = (NSDictionary *)errorObject;
                    errorMessage = errorDict[@"msg"] ?: errorDict[@"message"] ?: error.localizedDescription;
                    // 提取业务错误码
                    if (errorDict[@"code"]) {
                        businessCode = [errorDict[@"code"] integerValue];
                    }
                }
            }
            
            // 确定最终使用的错误码：优先使用业务错误码，如果没有则使用HTTP状态码
            NSInteger finalErrorCode = businessCode > 0 ? businessCode : (httpStatusCode > 0 ? httpStatusCode : error.code);
            
            // 确保回调在主线程执行
            dispatch_async(dispatch_get_main_queue(), ^{
                if (failed) {
                    failed(finalErrorCode, errorMessage);
                }
                
                [self handleCode:errorMessage code:finalErrorCode];
            });
        } else {
            // 解析响应数据
            id responseObject = nil;
            if (data && data.length > 0) {
                NSError *jsonError = nil;
                responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
            }
            
            // 确保回调在主线程执行
            dispatch_async(dispatch_get_main_queue(), ^{
                // 统一处理：只要HTTP状态码是200-299，就认为是成功，不检查业务code字段
                // 这样可以兼容所有后端接口，无论返回什么code结构
                if (httpStatusCode >= 200 && httpStatusCode < 300) {
                    // 处理直接返回数组的情况（如站点列表V2接口）
                    if ([responseObject isKindOfClass:[NSArray class]]) {
                        // 新接口直接返回数组，包装成字典格式以兼容现有代码
                        NSDictionary *dic = @{@"data": responseObject, @"code": @(httpStatusCode)};
                        NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                        NSLog(@"📥 GET 响应成功 (直接返回数组，已包装)");
                        NSLog(@"HTTP状态码: %ld", (long)httpStatusCode);
                        NSLog(@"出参: %@", responseObject);
                        NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                        _currentRequestURL = nil;  // 请求成功，清除URL
                        succeed(dic, httpStatusCode);
                        return;
                    }
                    
                    // 处理返回字典的情况
                    if ([responseObject isKindOfClass:[NSDictionary class]]) {
                        NSDictionary *dic = (NSDictionary *)responseObject;
                        // 无论业务code是什么值，只要HTTP状态码是200-299就成功
                        NSInteger businessCode = [dic[@"code"] integerValue];
                        NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                        NSLog(@"📥 GET 响应成功");
                        NSLog(@"HTTP状态码: %ld", (long)httpStatusCode);
                        NSLog(@"业务code: %ld", (long)businessCode);
                        NSLog(@"出参: %@", dic);
                        NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                        _currentRequestURL = nil;  // 请求成功，清除URL
                        succeed(dic, httpStatusCode);
                        return;
                    }
                    
                    // 其他类型（如字符串等），也包装成字典格式
                    NSDictionary *dic = @{@"data": responseObject ?: @{}, @"code": @(httpStatusCode)};
                    NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                    NSLog(@"📥 GET 响应成功 (其他类型，已包装)");
                    NSLog(@"HTTP状态码: %ld", (long)httpStatusCode);
                    NSLog(@"出参: %@", responseObject);
                    NSLog(@"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
                    _currentRequestURL = nil;  // 请求成功，清除URL
                    succeed(dic, httpStatusCode);
                } else {
                    // HTTP状态码不在200-299范围内，认为是失败
                    NSDictionary *dic = ([responseObject isKindOfClass:[NSDictionary class]]) ? (NSDictionary *)responseObject : @{};
                    NSString *errorMsg = dic[@"message"] ?: dic[@"msg"] ?: @"请求失败";
                    
                    // 提取业务错误码（如果存在）
                    NSInteger businessCode = 0;
                    if (dic[@"code"]) {
                        businessCode = [dic[@"code"] integerValue];
                    }
                    
                    // 确定最终使用的错误码：优先使用业务错误码，如果没有则使用HTTP状态码
                    NSInteger finalErrorCode = businessCode > 0 ? businessCode : httpStatusCode;
                    
                    NSLog(@"❌ 失败 URL = %@ HTTP:%ld 业务code:%ld params = %@", tempUrl, (long)httpStatusCode, (long)businessCode, params);
                    failed(finalErrorCode, errorMsg);
                    [self handleCode:errorMsg code:finalErrorCode];
                }
            });
        }
    }];
    [requestTask resume];
    return requestTask;
}

- (NSURLSessionDataTask *)DELETE:(NSString *)url params:(nullable NSDictionary *)params succeed:(SucceedBlock)succeed failed:(Failed)failed  {
    
    [self br_config];
    NSString *tempUrl = [BASE_URL stringByAppendingString:url];
    
    NSMutableURLRequest *request = [self br_configRequest:tempUrl parmas:params byMethod:DELETE];
    [request setHTTPMethod:@"DELETE"];
    
    NSURLSessionDataTask *requestTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 确保回调在主线程执行
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                NSLog(@"请求失败 err = %@ \n url = %@\n 参数= %@",error,tempUrl,params);
                if (failed) {
                    failed(error.code,error.localizedDescription);
                }
                [self handleCode:error.localizedDescription code:error.code];
            } else {
                // 解析响应数据
                NSDictionary *dic = nil;
                if (data && data.length > 0) {
                    NSError *jsonError = nil;
                    id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                    if (!jsonError && [responseObject isKindOfClass:[NSDictionary class]]) {
                        dic = (NSDictionary *)responseObject;
                    }
                }
                
                if (!dic) {
                    dic = @{};
                }
                
                NSInteger status = [dic[@"code"] integerValue];
                
                if (status == 0) {
                    NSLog(@"请求 成功 == %ld",status);
                    succeed(dic,status);
                }else {
                    NSLog(@"失败 URL = %@ params = %@\n",tempUrl,params);
                    failed(status,dic[@"message"] ?: @"请求失败");
                    if (status == 21012) {
                        return;
                    }
                
                    [self handleCode:dic[@"message"] ?: @"请求失败" code:status];
                }
            }
        });
    }];
    
    [requestTask resume];
    return requestTask;
}

- (void)handleCode:(NSString *)message code:(NSInteger)code {
    
    // 失败后一些处理
    NSLog(@"error = %@(%ld)",message,code);
    
    // 添加容错处理，避免空消息导致崩溃
    if (!message || message.length == 0) {
        message = @"网络请求失败，请稍后重试";
    }
    
    // 处理登录过期错误：10401 或 460
    if (code == 10401 || code == 460) {
        NSLog(@"📍 检测到登录过期错误（code=%ld），清除登录状态并跳转到登录页面", (long)code);
        
        [[BRUserManager share] logoutClean];
        
        // 显示提示并跳转到登录页面
        BRCustiomAlertView *alertV = [[BRCustiomAlertView alloc] initWithTitle:Localized(@"set_logout") subTitle:message cancelStr:Localized(@"profile_confirm") succStr:@"" cancelAction:^{
            //退出登录，跳转到登录页面
            [[BRUserManager share] toChangeRootVC];
        } successAction:^{
            //退出登录，跳转到登录页面
            [[BRUserManager share] toChangeRootVC];
        } showBC:YES];
        
        UIViewController *window =  [UIApplication sharedApplication].delegate.window.rootViewController;
        [window.view addSubview:alertV];
        return;
    }
    
    // 特殊处理：支付轮询接口（/security/pay/check）不显示错误提示
    // 因为500错误表示订单未支付成功，这是正常状态，不应该显示错误
    if (_currentRequestURL && ([_currentRequestURL containsString:@"/security/pay/check"] || [_currentRequestURL containsString:@"/app/security/pay/check"])) {
        NSLog(@"📍 [支付轮询] 检测到支付轮询接口，不显示错误提示: %@", message);
        _currentRequestURL = nil;  // 清除URL
        return;
    }
    
    // 特殊处理：rentbox/show.html/V2 接口的 3840 错误（有进行中的订单或未支付订单）
    // 由调用方自己处理，不显示全局错误提示
    if (code == 3840 && _currentRequestURL && [_currentRequestURL containsString:@"/sw/app/rentbox/show.html/V2"]) {
        NSLog(@"📍 [rentbox/show.html/V2] 检测到3840错误，不显示全局错误提示，由调用方处理: %@", message);
        _currentRequestURL = nil;  // 清除URL
        return;
    }
    
    // 显示错误提示，但不要阻塞应用
    dispatch_async(dispatch_get_main_queue(), ^{
        [BRHud showTips:message];
    });
    
    // 清除URL
    _currentRequestURL = nil;
}


#pragma mark - 网络环境监听 --
// C函数回调，用于网络状态监听
static void NetworkReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) {
    dispatch_async(dispatch_get_main_queue(), ^{
        if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) {
            NSLog(@"无网络");
            [BRHud showTips:@"网络连接失败，请检查网络设置"];
        } else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) {
            NSLog(@"手机网络");
        } else {
            NSLog(@"WIFI");
        }
    });
}

+ (void)AFNReachability {
    // 使用系统API监听网络状态
    static SCNetworkReachabilityRef reachability = NULL;
    
    if (reachability == NULL) {
        reachability = SCNetworkReachabilityCreateWithName(NULL, "www.apple.com");
        
        SCNetworkReachabilityContext context = {0, NULL, NULL, NULL, NULL};
        
        // 使用C函数指针而不是block
        SCNetworkReachabilitySetCallback(reachability, NetworkReachabilityCallback, &context);
        
        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    }
}


@end
